﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace ClassLibrary
{
    /* class for actions with diffent structures as massives */
    public static class Supplimentary
    {
        /* 
         * Method
         * Does: summurazes all values in massive
         * Args: int massive
        */
        public static int sumIntMassive(int[] mas)
        {
            int sum = 0;
            foreach (int value in mas)
            {
                sum += value;
            }
            return sum;
        }


       /* 
        * Method
        * Does: summurazes all values in massive
        * Args: UInt64 massive
       */
        public static UInt64 sumUInt64Massive(UInt64[] mas)
        {
            UInt64 sum = 0;
            foreach (UInt64 value in mas)
            {
                sum += value;
            }
            return sum;
        }


        /* 
         * Method
         * Does: adds to fist massive values from second one
         * Args: UInt64 2-dimensional massive 
         *       UInt64 2-dimensional massive 
        */
        public static void addUInt64UInt64TwoDimensionalToFirstMassiveSecondOne(Dictionary<int, UInt64[]> mas1, Dictionary<int, UInt64[]> mas2)
        {
            int i = -1;
            foreach (UInt64[] massive in mas2.Values)
            {
                i++;
                int j = -1;
                foreach (UInt64 value in mas2[i])
                {
                    j++;
                    mas1[i][j] += value;
                }
            }
        }


        /* 
           * Method
           * Does: adds to fist massive values from second one
           * Args: double 1-dimensional massive 
           *       int 1-dimensional massive 
          */
        public static void addDoubleIntOneDimensionalToFirstMassiveSecondOne(double[] mas1, int[] mas2)
        {
            int i = -1;
            foreach (int value in mas2)
            {
                i++;
                mas1[i] += value;
            }
        }
    }


    /* base class for tree nodes */
    public class BaseNode { }


    /* end event tree node */
    public class EventEndNode : BaseNode
    {
        public Event end_node_event;

        /* constructor */
        public EventEndNode(Event even)
        {
            end_node_event = even;
        }
    }


    /* main  event tree node*/
    public class EventLinkNode : BaseNode
    {
        public int massive_nodes_size { set; get; }
        public BaseNode[] massive_nodes;

        /* constructor */
        public EventLinkNode(int[] level_sizes)
        {
            // setting current level_size
            massive_nodes_size = level_sizes[0];

            // condition for end_nodes
            if (level_sizes.Count() == 1)
            {
                massive_nodes = new EventEndNode[massive_nodes_size];
            }
            else
            {
                // creating next tree level
                massive_nodes = new EventLinkNode[massive_nodes_size];

                // creating new level sizes massive
                int[] new_level_sizes = level_sizes.Where((val, idx) => idx != 0).ToArray();

                // creating new tree's level
                for (int i = 0; i < massive_nodes_size; i++)
                {
                    massive_nodes[i] = new EventLinkNode(new_level_sizes);
                }
            }
        }

        public void addEndNode(int id, EventEndNode end_node)
        {
            massive_nodes[id] = end_node;
        }

        public void setEndNode(int[] character_vector, Event even)
        {
            // condition for end_nodes
            if (character_vector.Count() == 1)
            {
                massive_nodes[character_vector[0]] = new EventEndNode(even);
            }
            else
            {
                // going to next tree level

                int[] sub_character_vector = character_vector.Where((val, idx) => idx != 0).ToArray();
                ((EventLinkNode)massive_nodes[character_vector[0]]).setEndNode(sub_character_vector, even);
            }
        }

        public Event getEndNode(int[] character_vector)
        {
            // condition for end_nodes
            if (character_vector.Count() == 1)
            {
                return ((EventEndNode)massive_nodes[character_vector[0]]).end_node_event;
            }
            else
            {
                // going to next tree level

                int[] sub_character_vector = character_vector.Where((val, idx) => idx != 0).ToArray();
                return ((EventLinkNode)massive_nodes[character_vector[0]]).getEndNode(sub_character_vector);
            }
        }
    }


    // wrapping class for int massive
    public class IntMassive
    {
        public int[] massive;

        public IntMassive() {}

        public IntMassive(int size)
        {
            massive = new int[size];
        }

        public bool Equals(IntMassive other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;

            bool equals = true;

            for (int i = 0; i < massive.Count(); i++)
            {
                if (massive[i] != other.massive[i])
                {
                    equals = false;
                    break;
                }
            }

            return equals;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(IntMassive)) return false;
            return Equals((IntMassive)obj);
        }

        public override int GetHashCode()
        {
            return 0;
        }
    }   
}
